GhostMountDB = {
	["PetOnDismount"] = true,
	["IgnoreList"] = { },
}

local superFastFlyingMountIDs = {
	[58615] = true,
	[44744] = true,
	[37015] = true,
	[49193] = true,
}
	
local fastFlyingMountIDs = {
	[54729] = true,
	[48025] = true,
	[32297] = true,
	[61230] = true,
	[61229] = true,
	[41514] = true,
	[39803] = true,
	[43927] = true,
	[41517] = true,
	[41518] = true,
	[59571] = true,
	[60002] = true,
	[44151] = true,
	[32242] = true,
	[32290] = true,
	[32295] = true,
	[61442] = true,
	[32292] = true,
	[32289] = true,
	[32246] = true,
	[61444] = true,
	[61446] = true,
	[32296] = true,
	[60025] = true,
	[59567] = true,
	[59650] = true,
	[59568] = true,
	[59996] = true,
	[59569] = true,
	[41515] = true,
	[43810] = true,
	[41513] = true,
	[41516] = true,
	[39801] = true,
	[59570] = true,
	[39800] = true,
	[39802] = true,
	[46199] = true,
	[59961] = true,
	[61309] = true,
	[51960] = true,
	[61294] = true,
	[39798] = true,
}

local slowFlyingMountIDs = {
	[48025] = true,
	[54729] = true,
	[32244] = true,
	[32239] = true,
	[61451] = true,
	[44153] = true,
	[32235] = true,
	[32245] = true,
	[3363] = true,
	[28828] = true,
	[32240] = true,
	[32243] = true,
	[46197] = true,
}

local fastLandMountIDs = {
	[48778] = true,
	[48025] = true,
	[34767] = true,
	[23214] = true,
	[23161] = true,
	[43688] = true,
	[16056] = true,
	[60114] = true,
	[60116] = true,
	[51412] = true,
	[58983] = true,
	[22719] = true,
	[16055] = true,
	[59572] = true,
	[26656] = true,
	[60118] = true,
	[60119] = true,
	[48027] = true,
	[22718] = true,
	[59785] = true,
	[59788] = true,
	[22720] = true,
	[22721] = true,
	[22717] = true,
	[22723] = true,
	[22724] = true,
	[39315] = true,
	[34896] = true,
	[39316] = true,
	[34790] = true,
	[59810] = true,
	[59811] = true,
	[61465] = true,
	[61467] = true,
	[60136] = true,
	[60140] = true,
	[59802] = true,
	[59804] = true,
	[35713] = true,
	[49379] = true,
	[23249] = true,
	[34407] = true,
	[23248] = true,
	[35712] = true,
	[35714] = true,
	[23247] = true,
	[23241] = true,
	[43900] = true,
	[23238] = true,
	[23229] = true,
	[23250] = true,
	[23220] = true,
	[23221] = true,
	[23239] = true,
	[23252] = true,
	[35025] = true,
	[23225] = true,
	[23219] = true,
	[23242] = true,
	[23243] = true,
	[23227] = true,
	[33660] = true,
	[35027] = true,
	[24242] = true,
	[42777] = true,
	[23338] = true,
	[23251] = true,
	[47037] = true,
	[35028] = true,
	[46628] = true,
	[23223] = true,
	[23240] = true,
	[23228] = true,
	[23222] = true,
	[48954] = true,
	[49322] = true,
	[24252] = true,
	[23246] = true,
	[41252] = true,
	[22722] = true,
	[39317] = true,
	[34898] = true,
	[39318] = true,
	[34899] = true,
	[54753] = true,
	[39319] = true,
	[34897] = true,
	[59573] = true,
	[36702] = true,
	[23509] = true,
	[17465] = true,
	[59797] = true,
	[59799] = true,
	[17459] = true,
	[18992] = true,
	[16082] = true,
	[16084] = true,
	[29059] = true,
	[15779] = true,
	[16083] = true,
	[17229] = true,
	[59791] = true,
	[59793] = true,
	[16081] = true,
	[579] = true,
	[16080] = true,
	[55531] = true,
	[60424] = true,
	[17481] = true,
	[23510] = true,
	[61469] = true,
	[61470] = true,
	[61425] = true,
	[61447] = true,
}

local aqMountIDs = {
	[25953] = true,
	[26056] = true,
	[26054] = true,
	[26055] = true,
}

local f = CreateFrame("Frame")

local ownedMountIDs
local lastUsedID = 0

local lastUsedPetIndex = 0

local function GetRandomPetIndexFromTable()
	local rc
	
	
	if GetNumCompanions("CRITTER") then
		while true do
			local index = math.random(1, GetNumCompanions("CRITTER"))
			local id = select(3, GetCompanionInfo("CRITTER", index))
			
	
			if id == 26529 and GetNumCompanions("CRITTER") == 1 then
				rc = nil
				break
			else
				if ( id ~= 26529 and index ~= lastUsedPetIndex ) or GetNumCompanions("CRITTER") == 1 then
					rc = index
					break
				end
			end
		end
	end
		
	return rc
end

local function CallPet()
	local random = GetRandomPetIndexFromTable()
	
	
	if random ~= nil then
		CallCompanion("CRITTER", random)
		lastUsedPetIndex = random
	end
end

local function ConditionalDismount(forceFlyingDismount)
	-- returns TRUE if an attempt to mount up should be ABORTED
	local rc = false
	
	
	if not IsFlying() or forceFlyingDismount then
		if IsMounted() then
			Dismount()
			
			if GhostMountDB.PetOnDismount then
				CallPet()
			end
			
			rc = true
		end
	else
		rc = true
	end
	
	return rc
end

local function IsAcceptableID(id, count)
	local rc
	
	
	if count == 1 then
		rc = true
	else
		rc = (id ~= lastUsedID)
	end
	
	return rc
end

local function GetRandomMountIDFromTable(mounts)
	local rc
	
	
	while true do
		local rand = math.random(1, mounts.count)
		
		
		if IsAcceptableID(mounts[rand], mounts.count) then
			rc = mounts[rand]
			break
		end
	end
	
	return rc
end

local function ScanMounts()
	ownedMountIDs = { [75] = { }, [150] = { }, [225] = { }, [300] = { }, ["AQ"] = { }, ["Arena"] = { } }	
	GhostMountDB.IgnoreList = GhostMountDB.IgnoreList or { }
	
	for i = 1, GetNumCompanions("MOUNT") do
		local id = select(3, GetCompanionInfo("MOUNT", i))
		
		
		if not GhostMountDB.IgnoreList[id] then
			local level
			
			
			if aqMountIDs[id] then
				level = "AQ"
			elseif superFastFlyingMountIDs[id] then
				level = 300 -- for now
			elseif fastFlyingMountIDs[id] then
				level = 300
			elseif slowFlyingMountIDs[id] then
				level = 225
			elseif fastLandMountIDs[id] then
				level = 150
			else
				level = 75
			end
		
			ownedMountIDs[level].count = ownedMountIDs[level].count or 0
			ownedMountIDs[level].count = ownedMountIDs[level].count + 1
			ownedMountIDs[level][ownedMountIDs[level].count] = id
		end
	end
end

local function CallMountWithID(id)
	for i = 1, GetNumCompanions("MOUNT") do
		local foundID = select(3, GetCompanionInfo("MOUNT", i))
		
		
		if foundID == id then
			CallCompanion("MOUNT", i)
			lastUsedID = id
			break
		end
	end
end

local function Display()
	local i
	
	
	DEFAULT_CHAT_FRAME:AddMessage("Mounts...")
	
	for i = 1, GetNumCompanions("MOUNT") do
		local _, name, id = GetCompanionInfo("MOUNT", i)
		
		
		DEFAULT_CHAT_FRAME:AddMessage(string.format("Name: '%s', Creature Spell ID: '%s'", name, id))
	end

	DEFAULT_CHAT_FRAME:AddMessage("Pets...")

	for i = 1, GetNumCompanions("CRITTER") do
		local _, name, id = GetCompanionInfo("CRITTER", i)
		
		
		DEFAULT_CHAT_FRAME:AddMessage(string.format("Name: '%s', Creature Spell ID: '%s'", name, id))
	end
end

local function CallNormalLandMount()
	local mountTable = ownedMountIDs[150]
	local randomNumber
	
	
	if mountTable.count == nil then
		mountTable = ownedMountIDs[75]
	end
	
	if mountTable.count ~= nil then
		local id = GetRandomMountIDFromTable(mountTable)
		CallMountWithID(id)
	else
		DEFAULT_CHAT_FRAME:AddMessage("Ghost: Mount - no appropriate mounts found.")
	end	
end

local function CallLandMount()
	if ConditionalDismount() == false then
		local mountTable = ownedMountIDs["AQ"]
		
		
		if mountTable.count == nil or GetRealZoneText() ~= "Ahn'Qiraj" then
			CallNormalLandMount()
		else
			local id = GetRandomMountIDFromTable(mountTable)
			CallMountWithID(id)
		end
	end
end

local function CallFlyingMount(forceFlyingDismount)
	if ConditionalDismount(forceFlyingDismount) == false then
		local mountTable = ownedMountIDs["Arena"]
		
		
		if mountTable.count == nil then
			mountTable = ownedMountIDs[300]
		end
		
		if mountTable.count == nil then
			mountTable = ownedMountIDs[225]
		end
		
		if mountTable.count ~= nil then
			local id = GetRandomMountIDFromTable(mountTable)
			CallMountWithID(id)
		else
			CallNormalLandMount()
		end
	end
end

function CanFly()
	local rc = IsFlyableArea()
	
	
	if rc then
		if UnitLevel("player") < 77 then
			local znes = { "Dalaran", "Borean Tundra", "Howling Fjord", "Sholazar Basin", "Icecrown", "The Storm Peaks", "Zul'Drak", "Grizzly Hills", "Dragonblight", "Crystalsong Forest" }
			
			
			for _, v in pairs(znes) do
				if GetRealZoneText() == v then
					rc = nil
					break
				end
			end
			
		elseif GetRealZoneText() == "Dalaran" then
			rc = nil
			
			if GetSubZoneText() == "Krasus' Landing" then
				if IsIndoors() then
					rc = nil
				else
					rc = 1
				end
			else
				rc = nil
			end
		elseif GetRealZoneText() == "Wintergrasp" then
			rc = nil
		end
	end
	
	return rc
end

local function CallLandMountNoFlyable()
	if ConditionalDismount() == false then
		if not CanFly() then
			CallLandMount()
		end
	end
end

local function CallBestMount(forceFlyingDismount)
	if CanFly() then
		CallFlyingMount(forceFlyingDismount)
	else
		CallLandMount()
	end
end

function GetNormalLandMountId()
	local mountTable = ownedMountIDs[150]
	local randomNumber
	
	
	if mountTable.count == nil then
		mountTable = ownedMountIDs[75]
	end
	
	if mountTable.count ~= nil then
		local id = GetRandomMountIDFromTable(mountTable)
		return id
	else
		DEFAULT_CHAT_FRAME:AddMessage("Ghost: Mount - no appropriate mounts found.")
	end	
end

function GetLandMountId()
	local mountTable = ownedMountIDs["AQ"]
	
	
	if mountTable.count == nil or GetRealZoneText() ~= "Ahn'Qiraj" then
		return GetNormalLandMountId()
	else
		local id = GetRandomMountIDFromTable(mountTable)
		return id;
	end
end

local function GetFlyingMountId(forceFlyingDismount)
	local mountTable = ownedMountIDs["Arena"]
	
	
	if mountTable.count == nil then
		mountTable = ownedMountIDs[300]
	end
	
	if mountTable.count == nil then
		mountTable = ownedMountIDs[225]
	end
	
	if mountTable.count ~= nil then
		local id = GetRandomMountIDFromTable(mountTable)
		return id
	else
		return GetNormalLandMountId()
	end
end

function GetBestMountId(forceFlyingDismount)
	if ownedMountIDs == nil then
		ScanMounts()
	end
	if CanFly() then
		return GetFlyingMountId(forceFlyingDismount)
	else
		return GetLandMountId()
	end
end

function GetBestMountNames(forceFlyingDismount)
	if ownedMountIDs == nil then
		ScanMounts()
	end
	local ss = {}
	if CanFly() then
		local fly=GetFlyingMountId(forceFlyingDismount)
		if(fly~=nil)then
			ss[#ss+1]=GetMountNameWithID(fly)
		end
	end
	local land=GetLandMountId()
	if(land~=nil)then
		ss[#ss+1]=GetMountNameWithID(land)
	end	
	return ss;
end

function GetMountNameWithID(id)
	for i = 1, GetNumCompanions("MOUNT") do
		local creatureID, creatureName, creatureSpellID, icon, issummoned =  GetCompanionInfo("MOUNT", i)
		local foundID = creatureSpellID
		
		if foundID == id then
			lastUsedID = id
			return creatureName
			--break
		end
	end
end

local function TogglePet()
	GhostMountDB.PetOnDismount = not GhostMountDB.PetOnDismount
	
	if GhostMountDB.PetOnDismount then
		DEFAULT_CHAT_FRAME:AddMessage("Ghost: Mount - A vanity pet will be automatically summoned upon dismounting.")
	else
		DEFAULT_CHAT_FRAME:AddMessage("Ghost: Mount - A vanity pet will no longer be automatically summoned upon dismounting.")
	end
end

local function DisplayHelp()
	DEFAULT_CHAT_FRAME:AddMessage("Ghost: Mount usage:")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount best (fastest flying mount in flying areas or fastest land mount otherwise)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount forcedismount (same as /mount best except it allows dismounting while flying)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount display (shows your mounts and pets)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount flying (fastest flying mount, and if you don't have one, you'll get a land mount)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount land (fastest land mount)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount landstrict (fastest land mount, but does nothing if you're able to fly)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount pet (summons a vanity pet)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount ignore <name> (ignores a mount - won't be summoned)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount unignore <name> (un-ignores a mount - can be summoned again)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount listignored (shows all currently ignored mounts)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount togglepet (switches pets on dismount on and off)")
	DEFAULT_CHAT_FRAME:AddMessage("    /mount help")
end

local function ListIgnored()
	local i
	local count = 0
		
	
	DEFAULT_CHAT_FRAME:AddMessage("Ghost: Mount - List of ignored mounts...")

	GhostMountDB.IgnoreList = GhostMountDB.IgnoreList or { }

	for i = 1, GetNumCompanions("MOUNT") do
		local _, name, id = GetCompanionInfo("MOUNT", i)
		
		
		if GhostMountDB.IgnoreList[id] then
			DEFAULT_CHAT_FRAME:AddMessage("    - "..name)
			count = count + 1
		end
	end
	
	if count == 0 then
		DEFAULT_CHAT_FRAME:AddMessage("*** NONE ***")
	else
		DEFAULT_CHAT_FRAME:AddMessage("Total ignored: "..count)
	end
end


local function SetMountIgnoreState(patt, state)
	local i
	
	
	GhostMountDB.IgnoreList = GhostMountDB.IgnoreList or { }
	
	for i = 1, GetNumCompanions("MOUNT") do
		local _, curName, id = GetCompanionInfo("MOUNT", i)
		local lowerName = string.lower(curName)
		
		if string.find(lowerName, patt) then
			if state then
				GhostMountDB.IgnoreList[id] = state
				DEFAULT_CHAT_FRAME:AddMessage("Ghost: Mount - Now ignoring "..curName..".")
			else
				GhostMountDB.IgnoreList[id] = nil
				DEFAULT_CHAT_FRAME:AddMessage("Ghost: Mount - Now allowing "..curName..".")
			end
		end
	end
end

local function IgnoreMount(name)
	name = string.lower(name)

	if name ~= nil and string.len(name) > 0 then
		SetMountIgnoreState(name, true)
		ownedMountIDs = nil	
	end
end

local function UnignoreMount(name)
	name = string.lower(name)

	if name ~= nil and string.len(name) > 0 then
		SetMountIgnoreState(name, false)	
		ownedMountIDs = nil	
	end
end

local stealthSpells = {
	[5215] = true,
	[6783] = true,
	[9913] = true,
	
	[1784] = true,
	[1785] = true,
	[1786] = true,
	[1787] = true,
}

local function OnEvent(this, event, timeStamp, combatEvent, sourceGuid, sourceName, sourceFlags, destGuid, destName, destFlags, spellId, spellName, spellSchool, auraType)
	local hidePet = false
	local isIn, instType = IsInInstance()
	
	
	if instType == "pvp" or instType == "arena" then
		hidePet = true
	elseif UnitIsPVP("player") then
		hidePet = true
	elseif UnitIsPVPFreeForAll("player") then
		hidePet = true
	end
	
	if hidePet then
		if combatEvent == "SPELL_AURA_APPLIED" then
			if destName == UnitName("player") then
				if stealthSpells[spellId] then
					DismissCompanion("CRITTER")
				end
			end
		end
	end
end

local commandDispatch = {
	["best"] = function() CallBestMount(false) end,
	["flying"] = function() CallFlyingMount(false) end,
	["forcedismount"] = function() CallBestMount(true) end,
	["display"] = Display,
	["help"] = DisplayHelp,
	["ignore"] = IgnoreMount,
	["unignore"] = UnignoreMount,
	["listignored"] = ListIgnored,
	["land"] = CallLandMount,
	["landstrict"] = CallLandMountNoFlyable,
	["pet"] = CallPet,
	["togglepet"] = TogglePet,
}

local function CommandHandler(...)
	local commandLine = SecureCmdOptionParse(...)
	local subCommand = select(1, commandLine)
	local params = ""
	local posn
	
	
	if subCommand ~= nil then
		posn = string.find(subCommand, " ")
		
		
		-- sort out the command line	
		if posn then
			params = string.sub(subCommand, posn + 1, string.len(subCommand))
			subCommand = string.sub(subCommand, 1, posn-1)
		end
	end
		
	-- scan owned mounts
	if ownedMountIDs == nil then
		ScanMounts()
	end
	
	-- dispatch the command
	local f = commandDispatch[subCommand]


	if f then
		f(params)
	end
end

SlashCmdList["GHOSTMOUNT"] = CommandHandler
SLASH_GHOSTMOUNT1 = "/ghostmount"
SLASH_GHOSTMOUNT2 = "/gmount"
SLASH_GHOSTMOUNT3 = "/mount"

f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
f:SetScript("OnEvent", OnEvent)
f:Show()
